#ifndef _TUNNEL_MESSAGE__H_
#define _TUNNEL_MESSAGE__H_

#include <memory>

namespace VL {

/**
 * @Author: CimZzz
 * @Date: 2022-07-15 11:56:19
 * 
 * 管道数据
 */
class TunnelData {
public:
	/**
	 * @Author: CimZzz
	 * @Date: 2022-07-15 11:57:11
	 * 
	 * 构造方法
	 * @param dataPtr 数据指针
	 * @param dataLength 数据长度
	 */
	TunnelData(std::shared_ptr<void> dataPtr = std::shared_ptr<void>(nullptr), unsigned int dataLength = 0);

	/**
	 * @Author: CimZzz
	 * @Date: 2022-07-15 11:57:33
	 * 
	 * 模板实例化方法
	 * @param dataPtr 数据指针
	 * @return 管道数据指针
	 */
	template<typename T>
	static std::shared_ptr<TunnelData> newData(T* dataPtr) {
		return std::shared_ptr<TunnelData>(new TunnelData(std::shared_ptr<void>(dataPtr), sizeof(T)));
	}

	/**
	 * @Author: CimZzz
	 * @Date: 2022-07-15 11:57:33
	 * 
	 * 模板实例化方法
	 * @param dataPtr 数据指针
	 * @return 管道数据指针
	 */
	template<typename T>
	static std::shared_ptr<TunnelData> newData(std::shared_ptr<T> dataPtr) {
		return std::shared_ptr<TunnelData>(new TunnelData(std::shared_ptr<void>(dataPtr), sizeof(T)));
	}

	/**
	 * @Author: CimZzz
	 * @Date: 2022-07-14 18:51:20
	 * 
	 * 获取数据指针
	 * 
	 * @return 数据指针
	 */
	std::shared_ptr<void> getData() const;

	/**
	 * @Author: CimZzz
	 * @Date: 2022-07-15 16:41:06
	 * 
	 * 获取数据长度
	 * 
	 * @return 数据长度
	 */
	unsigned int getDataLength() const;

	/**
	 * @Author: CimZzz
	 * @Date: 2022-07-14 19:04:14
	 * 
	 * 获取基本数据类型转换后的数据指针
	 * 
	 * @attention 这里只允许基本数据类型转化, 其余转换将会抛出异常
	 * 
	 * @return 转换后的数据指针
	 */
	template<typename T, typename E>
	inline std::shared_ptr<E> dataCast() const {
		return std::shared_ptr<E>(new E(*memoryCast<T>().get()));
	}

	/**
	 * @Author: CimZzz
	 * @Date: 2022-07-14 19:04:14
	 * 
	 * 获取类型转换后的数据指针
	 * 
	 * @return 转换后的数据指针
	 */
	template<typename T, typename E>
	inline std::shared_ptr<E> typeCast() const {
		return std::static_pointer_cast<E, T>(memoryCast<T>());
	}

	/**
	 * @Author: CimZzz
	 * @Date: 2022-07-14 19:04:14
	 * 
	 * 获取内存转换后的数据指针
	 * 
	 * @return 转换后的数据指针
	 */
	template<typename T>
	inline std::shared_ptr<T> memoryCast() const {
		return std::static_pointer_cast<T, void>(this->dataPtr);
	}

private:
	/**
	 * @Author: CimZzz
	 * @Date: 2022-07-14 18:49:53
	 * 
	 * 数据指针
	 */
	std::shared_ptr<void> dataPtr;

	/**
	 * @Author: CimZzz
	 * @Date: 2022-07-15 14:36:45
	 * 
	 * 数据长度
	 */
	unsigned int dataLength;
};

/**
 * @Author: CimZzz
 * @Date: 2022-07-14 18:47:49
 * 
 * 通道消息
 * 通道之间除数据外, 还可以双向传递消息
 */
class TunnelMessage {
public:

	/**
	 * @Author: CimZzz
	 * @Date: 2022-07-14 18:49:26
	 * 
	 * 构造方法
	 * @param messageCode 消息码
	 * @param data 数据智能指针
	 * @param dataLength 数据长度
	 */
	TunnelMessage(unsigned long messageCode, std::shared_ptr<void> dataPtr = std::shared_ptr<void>(nullptr), unsigned int dataLength = 0);

	/**
	 * @Author: CimZzz
	 * @Date: 2022-07-14 18:49:26
	 * 
	 * 构造方法
	 * @param messageCode 消息码
	 * @param tunnelData 管道数据
	 */
	TunnelMessage(unsigned long messageCode, std::shared_ptr<TunnelData> tunnelData);

	/**
	 * @Author: CimZzz
	 * @Date: 2022-07-15 15:09:43
	 * 
	 * 模板实例化消息
	 * @param messageCode 消息码
	 * @param dataPtr 数据指针
	 */
	template<typename T>
	static std::shared_ptr<TunnelMessage> newMessage(unsigned long messageCode, T* dataPtr) {
		return std::shared_ptr<TunnelMessage>(new TunnelMessage(messageCode, std::shared_ptr<void>(dataPtr), sizeof(T)));
	}

	/**
	 * @Author: CimZzz
	 * @Date: 2022-07-15 15:09:43
	 * 
	 * 模板实例化消息
	 * @param messageCode 消息码
	 * @param dataPtr 数据指针
	 */
	template<typename T>
	static std::shared_ptr<TunnelMessage> newMessage(unsigned long messageCode, std::shared_ptr<T> dataPtr) {
		return std::shared_ptr<TunnelMessage>(new TunnelMessage(messageCode, std::shared_ptr<void>(dataPtr), sizeof(T)));
	}

	/**
	 * @Author: CimZzz
	 * @Date: 2022-07-14 18:50:21
	 * 
	 * 获取消息码
	 * 
	 * @return 消息码
	 */
	unsigned long getMessageCode() const;

	/**
	 * @Author: CimZzz
	 * @Date: 2022-07-15 16:45:51
	 * 
	 * 获取管道数据
	 * 
	 * @return 管道数据
	 */
	std::shared_ptr<TunnelData> getTunnelData() const;

	/**
	 * @Author: CimZzz
	 * @Date: 2022-07-14 18:51:20
	 * 
	 * 获取数据指针
	 * 
	 * @return 数据指针
	 */
	std::shared_ptr<void> getData() const;


	/**
	 * @Author: CimZzz
	 * @Date: 2022-07-15 16:41:06
	 * 
	 * 获取数据长度
	 * 
	 * @return 数据长度
	 */
	unsigned int getDataLength() const;
	


	/**
	 * @Author: CimZzz
	 * @Date: 2022-07-14 19:04:14
	 * 
	 * 获取基本数据类型转换后的数据指针
	 * 
	 * @attention 这里只允许基本数据类型转化, 其余转换将会抛出异常
	 * 
	 * @return 转换后的数据指针
	 */
	template<typename T, typename E>
	inline std::shared_ptr<E> dataCast() const {
		return this->dataPtr->dataCast<T, E>();
	}

	/**
	 * @Author: CimZzz
	 * @Date: 2022-07-14 19:04:14
	 * 
	 * 获取类型转换后的数据指针
	 * 
	 * @return 转换后的数据指针
	 */
	template<typename T, typename E>
	inline std::shared_ptr<E> typeCast() const {
		return this->dataPtr->typeCast<T>();
	}

	/**
	 * @Author: CimZzz
	 * @Date: 2022-07-14 19:04:14
	 * 
	 * 获取内存转换后的数据指针
	 * 
	 * @return 转换后的数据指针
	 */
	template<typename T>
	inline std::shared_ptr<T> memoryCast() const {
		return this->dataPtr->memoryCast<T>();
	}

private:
	/**
	 * @Author: CimZzz
	 * @Date: 2022-07-14 18:48:50
	 * 
	 * 消息码
	 */
	unsigned long messageCode;

	/**
	 * @Author: CimZzz
	 * @Date: 2022-07-14 18:49:53
	 * 
	 * 数据指针
	 */
	std::shared_ptr<TunnelData> dataPtr;
};

}

#endif // _TUNNEL_MESSAGE__H_
